#include "fletcher32.h"

#include <stdint.h>

#include "glog/logging.h"

// Optimized Fletcher-32 implementation.  Taken from 
//    http://en.wikipedia.org/wiki/Fletcher's_checksum#Optimizations
// on July 23, 2011

uint32_t fletcher32(const char* in_data, size_t byte_len) {
    CHECK((byte_len % 2) == 0);
    size_t len = byte_len / 2;
    const uint16_t* data = reinterpret_cast<const uint16_t*>(in_data);
    uint32_t sum1 = 0xffff, sum2 = 0xffff;

    while (len) {
        unsigned tlen = len > 360 ? 360 : len;
        len -= tlen;
        do {
            sum1 += *data++;
            sum2 += sum1;
        } while (--tlen);
        sum1 = (sum1 & 0xffff) + (sum1 >> 16);
        sum2 = (sum2 & 0xffff) + (sum2 >> 16);
    }
    /* Second reduction step to reduce sums to 16 bits */
    sum1 = (sum1 & 0xffff) + (sum1 >> 16);
    sum2 = (sum2 & 0xffff) + (sum2 >> 16);
    return sum2 << 16 | sum1;
}
